package sunyu.kit.mongodb;

import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.ReadPreference;
import com.mongodb.ServerAddress;
import com.mongodb.client.MongoDatabase;
import org.slf4j.Logger;
import sunyu.kit.common.LogKit;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * MongoDB工具类
 * <p>
 * http://mongodb.github.io/mongo-java-driver/3.3/driver/getting-started/installation-guide/
 *
 * @author 孙宇
 */
public class MongoDbKit {

    private static final Logger logger = LogKit.getLogger();

    private static final Map<String, MongoClient> mongoClientPool = new ConcurrentHashMap<>();//mongo客户端连接池

    /**
     * 系统关闭前调用此方法
     */
    public static void destroy() {
        logger.info("销毁MongoDB客户端连接开始");
        for (Map.Entry<String, MongoClient> entry : mongoClientPool.entrySet()) {
            entry.getValue().close();
        }
        logger.info("销毁MongoDB客户端连接结束");
    }

    /**
     * 添加客户端连接
     *
     * @param clientName 客户端名称
     * @param servers    连接地址，多个地址使用逗号分隔 localhost:27017,127.0.0.1:27107
     */
    public static void addClient(String clientName,
                                 String servers) {
        logger.info("添加MongoDB客户端连接：{}", clientName);
        if (mongoClientPool.containsKey(clientName)) {
            logger.error("MongoDB客户端 {} 已存在", clientName);
        } else {
            List<ServerAddress> serverAddressList = new ArrayList<>();
            for (String serverAddress : servers.split(",")) {
                String[] host = serverAddress.split(":");
                serverAddressList.add(new ServerAddress(host[0], Integer.parseInt(host[1])));
            }
            MongoClientOptions.Builder options = MongoClientOptions.builder();
            options.socketKeepAlive(true);// 是否保持长链接
            options.connectTimeout(5000);// 链接超时时间
            options.socketTimeout(5000); // read数据超时时间
            options.readPreference(ReadPreference.primary()); // 最近优先策略
            options.connectionsPerHost(30); // 每个地址最大请求数
            options.maxWaitTime(1000 * 60 * 2); // 长链接的最大等待时间
            options.threadsAllowedToBlockForConnectionMultiplier(50); // 一个socket最大的等待请求数
            MongoClient mongoClient = new MongoClient(serverAddressList, options.build());
            mongoClientPool.put(clientName, mongoClient);
        }
    }

    /**
     * 获得客户端连接
     *
     * @param clientName
     * @return
     */
    private static MongoClient getClient(String clientName) {
        return mongoClientPool.get(clientName);
    }

    /**
     * 获得数据库对象
     *
     * @param clientName   客户端名称
     * @param databaseName 数据库名称
     * @return
     */
    public static MongoDatabase getDatabase(String clientName,
                                            String databaseName) {
        return mongoClientPool.get(clientName).getDatabase(databaseName);
    }

}
